﻿using Coater.Helper.Modbus;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Coater.Helper
{
    /// <summary>
    /// 欧艾迪驱动器帮助类
    /// </summary>
    public class OidControllerHelper
    {
        /*
         *  控制模式()
            0: 电流控制模式
            1：转速控制模式
            2：占空比控制模式
            3：绝对位置控制模式
            4：相对上一次目标位置控制模式
            5：相对当前位置控制模式
            6：刹车电流控制模式
            7：手刹电流控制模式
            8：回零模式
            9：回零停止
            10： 电流爬升模式
            0xFFFF：空模式；uint16_t
         */
        /// <summary>
        /// 控制模式
        /// </summary>
        public int controlMode { get; set; }

        /// <summary>
        /// 串口号
        /// </summary>
        public string portName { get; set; }

        /// <summary>
        /// 波特率
        /// </summary>
        public int baudRate { get; set; } = 115200;

        /// <summary>
        /// modbus 从机地址
        /// </summary>
        public byte slaveAddress = 0x01;
        /// <summary>
        /// 连接状态
        /// </summary>
        public bool IsOpen => io is { IsOpen: true };

        /// <summary>
        /// 设置转速 （电角度转速（ERPM）） ERPM = RPM*磁极对数
        /// </summary>
        public int ERPM { get; set; }
        /// <summary>
        /// 当前转速 （电角度转速（ERPM）） ERPM = RPM*磁极对数
        /// </summary>
        public int ERPM_Curr { get; set; }
        /// <summary>
        /// 当前位置 单位 0.01度
        /// </summary>
        public int Position { get; set; }

        private IModbusHelper? io { get; set; }


        public bool Connect()
        {
            try
            {
                if (io is { IsOpen: true })
                {
                    return true;
                }
                io = new ModbusSerialHelper(portName, baudRate);

                Thread threadXinTiao = new Thread(XinTiao);
                threadXinTiao.IsBackground = true;
                threadXinTiao.Start();
                if (!(io is { IsOpen: true })) return false;

                io.WriteMultipleRegisters(slaveAddress, 6003, new ushort[] { 0, 0 });//设置转速为0
                io.WriteSingleRegister(slaveAddress, 6001, 0xFFFF);//设置模式为空模式
                return true;
            }
            catch (Exception ex)
            {
                LogHelper.ErrorLog.Error(ex);
                return false;
            }
        }

        UInt16 iXinTiao = 0;
        /// <summary>
        /// 心跳
        /// </summary>
        private void XinTiao()
        {
            while (io is { IsOpen: true })
            {
                iXinTiao = (ushort)(iXinTiao == 65535 ? 0 : iXinTiao + 1);

                io.WriteSingleRegister(slaveAddress, 6000, iXinTiao);

                ERPM = Convert.ToInt32(Convert.ToHexString(io.ReadHoldingRegisters(slaveAddress, 6003, 2)), 16);//设定转速

                ERPM_Curr = Convert.ToInt32(Convert.ToHexString(io.ReadInputRegisters(slaveAddress, 5001, 2)), 16);//实时转速

                //实时位置 单位 0.01度
                Position = Convert.ToInt32(Convert.ToHexString(io.ReadInputRegisters(slaveAddress, 5010, 2)), 16);//实时位置

                controlMode = Convert.ToInt32(Convert.ToHexString(io.ReadHoldingRegisters(slaveAddress, 6001, 1)), 16);//控制模式

                Thread.Sleep(500);
            }
        }

        /// <summary>
        /// 转速控制运行
        /// </summary>
        /// <param name="rpm"></param>
        public bool RunByRPM(int rpm)
        {
            try
            {
                string strHex = Convert.ToString(ERPM, 16).PadLeft(8, '0');
                ushort[] buffer = {
                Convert.ToUInt16(strHex.Substring(0,4),16),
                Convert.ToUInt16(strHex.Substring(4,4),16)
                };
                if (!io.WriteMultipleRegisters(slaveAddress, 6003, buffer)) return false;//设定转速
                if (!io.WriteSingleRegister(slaveAddress, 6001, 1)) return false;//设置模式
                Task.Run(() =>
                {
                    Thread.Sleep(1000);
                    io.WriteSingleRegister(slaveAddress, 6001, 0xFFFF);
                }).Wait();
                return true;
            }
            catch (Exception ex)
            {
                LogHelper.ErrorLog.Error(ex);
                return false;
            }
        }

        /// <summary>
        /// 绝对位置控制运行
        /// </summary>
        /// <param name="position"></param>
        /// <returns></returns>
        public bool RunByPosition(int position)
        {
            try
            {
                string strHex = Convert.ToString(Position, 16).PadLeft(8, '0');
                ushort[] buffer = {
                Convert.ToUInt16(strHex.Substring(0,4),16),
                Convert.ToUInt16(strHex.Substring(4,4),16)
            };
                if (!io.WriteMultipleRegisters(slaveAddress, 6006, buffer)) return false;//设定位置
                if (!io.WriteSingleRegister(slaveAddress, 6001, 3)) return false;//设置模式

                Task.Run(() =>
                {
                    Thread.Sleep(1000);
                    io.WriteSingleRegister(slaveAddress, 6001, 0xFFFF);
                });
                return true;
            }
            catch (Exception ex)
            {
                LogHelper.ErrorLog.Error(ex);
                return false;
            }
        }

    }
}
